package com.sunday.reactor.dome;

/**
 * @author mac
 */
public class Singleton {
	private volatile static Singleton uniqueInstance;
	
	private Singleton() {
	}
	
	public static Singleton getUniqueInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
	/*
		需要注意 uniqueInstance 必须采用 volatile进行修饰，否则极小概率可能出现对象未初始化完成的情况；具体过程如下：
		uniqueInstance = new Singleton(); 这段代码其实是分为三步执行：
		1. 为 uniqueInstance 分配内存空间
		2. 初始化 uniqueInstance
		3. 将 uniqueInstance 指向分配的内存地址
		但是由于 JVM 具有指令重排的特性，执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题，但是在多线程
		环境下会导致一个线程获得还没有初始化的实例。例如，线程 T1 执行了 1 和 3，此时 T2 调用 getUniqueInstance()
		后发现 uniqueInstance 不为空，因此返回 uniqueInstance，但此时 uniqueInstance 还未被初始化。
		使用 volatile 可以禁止 JVM 的指令重排，保证在多线程环境下也能正常运行。
	 */
}
